<script lang="ts" setup>
import { type PropType, ref, reactive, onMounted, h } from 'vue'
import {
  NSpace,
  NButton,
  cardProps,
  type FormInst,
  NForm,
  NFormItem,
  NH3,
  NTreeSelect,
  NInput,
  NInputNumber,
  NRadioButton,
  NSelect,
  NRadioGroup,
  type FormRules,
  useMessage
} from 'naive-ui'
import ModalContent from '@/components/ModalContent'
import type { UserModel } from '@/api/user'
import validator from 'validator'
import { sendRequest } from '@/utils/api'
import type { HttpResponse, HttpResponsePagination } from '@/utils/http'
import type { DicTreeModel } from '@/api/dic'
import type { RoleModel } from '@/api/role'
import { keysOf } from '@/utils/object'
import { RoleDicCode } from '@/enums/system'
import validatePassword from '../validatePassword'
import useRouteReplace from '@/hooks/useRouteReplace'
import { useRoute } from 'vue-router'

const route = useRoute()
const routeReplace = useRouteReplace(route.query.redirect as string)

const props = defineProps({
  ...cardProps,
  editId: {
    type: [Number, undefined] as PropType<number | undefined>
  }
})

const message = useMessage()
const baseFormRef = ref<FormInst | null>(null)
const userFormRef = ref<FormInst | null>(null)
const loading = ref(false)
const form = reactive<UserModel>({
  id: props.editId,
  password: props.editId ? null : 'Aa123456!',
  userStatus: 1
} as UserModel)
const confirmPassword = ref<string | null>(props.editId ? null : 'Aa123456!')
const featureRule = ref<number | null>(null)
const flowRule = ref<number | null>(null)
const formRules: FormRules = {
  userName: {
    required: true,
    trigger: 'blur',
    message: '用户名不能为空'
  },
  loginName: {
    required: true,
    trigger: 'blur',
    message: '登录名不能为空'
  },
  deptId: {
    required: true,
    trigger: ['blur', 'change'],
    type: 'number',
    message: '所属部门/单位不能为空'
  },
  password: {
    required: true,
    trigger: ['blur'],
    renderMessage: () => {
      if (!form.password) return '密码不能为空'
      const error = validatePassword(form.password)
      return error
        ? h(
            'p',
            {
              style: {
                maxWidth: '190px'
              }
            },
            error.message
          )
        : null
    },
    validator: (_, value) => {
      if (!value) return new Error()
      return validatePassword(value) || true
    }
  },
  confirmPassword: {
    required: true,
    trigger: ['input', 'blur'],
    validator: () => {
      if (!confirmPassword.value) return new Error('确认密码不能为空')
      return confirmPassword.value === form.password || new Error('两次密码不一致')
    }
  },
  featureRule: {
    required: true,
    trigger: ['blur', 'change'],
    validator: () => {
      if (!featureRule.value) return new Error('功能角色不能为空')
      return true
    }
  },
  phone: {
    required: true,
    trigger: ['input', 'blur'],
    validator: (_, value: string) => {
      if (!value) return new Error('手机号不能为空')
      return validator.isMobilePhone(value, 'zh-CN') || new Error('手机号格式不正确')
    }
  },
  mail: {
    trigger: ['input', 'blur'],
    validator: (_, value: string) => {
      if (!value) return true
      return validator.isEmail(value) || new Error('邮箱格式不正确')
    }
  }
}
const handleUpdateFeatureRule = (v: number, option: RoleModel) => {
  featureRule.value = v
  queryMenuOptions(option.id)
}

// 获取所属单位/部门
const filter = (e: DicTreeModel[]) => {
  const index = e.findIndex((c) => c.status === 0)
  if (index !== -1) e.splice(index, 1)
  e.forEach((c) => c.children && filter(c.children))
}
const depOptions = ref<DicTreeModel[] | undefined>(undefined)
const queryDepOptions = async () => {
  try {
    const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
      module: 'sysInstitution',
      api: 'getTree'
    })
    if (error) throw error
    filter(res.data)
    depOptions.value = res.data
  } catch (error: any) {
    message.error(error.message)
  }
}
// 获取功能角色
const featureOptions = ref<RoleModel[] | undefined>(undefined)
const queryFeatureOptions = async () => {
  try {
    const [error, res] = await sendRequest<HttpResponse<DicTreeModel>>({
      module: 'dic',
      api: 'infoByCode',
      uri: {
        code: RoleDicCode.Feature
      }
    })
    if (error) throw error
    const [roleError, roleRes] = await sendRequest<HttpResponsePagination<RoleModel>>({
      module: 'role',
      api: 'list',
      override: {
        params: {
          roleTypeId: res.data.id,
          limit: 10000
        }
      }
    })
    if (roleError) throw roleError
    featureOptions.value = roleRes.data.list
  } catch (error: any) {
    message.error(error.message)
  }
}
// 获取流程角色
const flowOptions = ref<RoleModel[] | undefined>(undefined)
const queryFlowOptions = async () => {
  try {
    const [error, res] = await sendRequest<HttpResponse<DicTreeModel>>({
      module: 'dic',
      api: 'infoByCode',
      uri: {
        code: RoleDicCode.Flow
      }
    })
    if (error) throw error
    const [roleError, roleRes] = await sendRequest<HttpResponsePagination<RoleModel>>({
      module: 'role',
      api: 'list',
      override: {
        params: {
          roleTypeId: res.data.id,
          limit: 10000
        }
      }
    })
    if (roleError) throw roleError
    flowOptions.value = roleRes.data.list
  } catch (error: any) {
    message.error(error.message)
  }
}
// 获取菜单
const menuOptions = ref<DicTreeModel[] | undefined>(undefined)
const queryMenuOptions = async (roleId: number) => {
  menuOptions.value = undefined
  // @ts-ignore
  form.menuId = null
  try {
    const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
      module: 'sysMenu',
      api: 'getTreeByRoleId',
      override: {
        params: {
          roleId
        }
      }
    })
    if (error) throw error
    menuOptions.value = res.data
  } catch (error: any) {
    message.error(error.message)
  }
}

const submit = async () => {
  const validate = await Promise.all([
    new Promise((resolve, reject) => {
      baseFormRef.value?.validate((error) => {
        if (error) return reject(error)
        resolve(true)
      })
    }),
    new Promise((resolve, reject) => {
      userFormRef.value?.validate((error) => {
        if (error) return reject(error)
        resolve(true)
      })
    })
  ])

  if (!validate.every(Boolean)) return

  loading.value = true
  const [error, res] = await sendRequest({
    module: 'user',
    api: props.editId ? 'update' : 'save',
    override: {
      data: {
        ...form,
        roleIdList: [featureRule.value, flowRule.value].filter(Boolean) as unknown as number[]
      } as UserModel
    }
  })
  loading.value = false

  if (error) return message.error(error.message)
  if (res.code !== 0) return message.error(res.msg)
  message.success(res.msg)
  window.flags.flushUser = true
  routeReplace()
}

onMounted(async () => {
  queryDepOptions()
  queryFlowOptions()
  await queryFeatureOptions()

  // 修改回显
  if (props.editId) {
    sendRequest<HttpResponse<UserModel>>({
      module: 'user',
      api: 'info',
      uri: {
        id: props.editId
      }
    }).then(([err, res]) => {
      if (err) return
      keysOf(res.data).forEach((e) => {
        if (e === 'functionRoleId') {
          return (featureRule.value = res.data.functionRoleId)
        }
        if (e === 'flowRoleId') {
          return (flowRule.value = res.data.flowRoleId)
        }
        form[e] = res.data[e] as never
      })

      const role = featureOptions.value?.find((e) => e.id === res.data.functionRoleId)
      if (!role) return
      queryMenuOptions(role.id)
    })
  }
})
</script>

<template>
  <ModalContent v-bind="$props">
    <NSpace style="gap: 0 50px; padding: 0 25px">
      <NSpace vertical>
        <NH3 prefix="bar">基本信息</NH3>
        <NForm
          :model="form"
          :rules="formRules"
          ref="baseFormRef"
          label-placement="left"
          label-width="115"
          size="small"
        >
          <NFormItem
            label="用户名"
            path="userName"
          >
            <NInput v-model:value="form.userName" />
          </NFormItem>
          <NFormItem
            label="所属单位/部门"
            path="deptId"
          >
            <NTreeSelect
              v-model:value="form.deptId"
              :options="depOptions"
              key-field="id"
              label-field="name"
              filterable
              :filter="(_, e) => !e.status"
            />
          </NFormItem>
          <NFormItem
            label="职务/职位"
            path="job"
          >
            <NInput v-model:value="form.job" />
          </NFormItem>
          <NFormItem
            label="手机号"
            path="phone"
          >
            <NInput v-model:value="form.phone" />
          </NFormItem>
          <NFormItem
            label="邮箱"
            path="mail"
          >
            <NInput v-model:value="form.mail" />
          </NFormItem>
          <NFormItem
            label="排序码"
            path="orderIndex"
          >
            <NInputNumber v-model:value="form.orderIndex" />
          </NFormItem>
          <NFormItem
            label="状态"
            path="userStatus"
          >
            <NRadioGroup v-model:value="form.userStatus">
              <NRadioButton
                :value="1"
                label="正常"
              />
              <NRadioButton
                :value="0"
                label="禁用"
              />
            </NRadioGroup>
          </NFormItem>
        </NForm>
      </NSpace>
      <NSpace vertical>
        <NH3 prefix="bar">用户信息</NH3>
        <NForm
          :model="form"
          :rules="formRules"
          ref="userFormRef"
          label-placement="left"
          label-width="110"
        >
          <NFormItem
            label="登录名"
            path="loginName"
          >
            <NInput v-model:value="form.loginName" />
          </NFormItem>
          <template v-if="!editId">
            <NFormItem
              label="密码"
              path="password"
            >
              <NInput
                v-model:value="form.password"
                show-password-on="click"
                type="password"
              />
            </NFormItem>
            <NFormItem
              label="确认密码"
              path="confirmPassword"
            >
              <NInput
                v-model:value="confirmPassword"
                show-password-on="click"
                type="password"
              />
            </NFormItem>
          </template>
          <NFormItem
            label="功能角色"
            path="featureRule"
          >
            <NSelect
              :value="featureRule"
              @update:value="handleUpdateFeatureRule"
              :options="featureOptions"
              label-field="roleName"
              value-field="id"
            />
          </NFormItem>
          <NFormItem
            label="流程角色"
            path="flowRule"
          >
            <NSelect
              v-model:value="flowRule"
              :options="flowOptions"
              label-field="roleName"
              value-field="id"
            />
          </NFormItem>
          <NFormItem
            label="用户首页地址"
            path="menuId"
          >
            <NTreeSelect
              v-model:value="form.menuId"
              :disabled="!menuOptions"
              :options="menuOptions"
              key-field="id"
              label-field="name"
              clearable
            />
          </NFormItem>
        </NForm>
      </NSpace>
    </NSpace>

    <template #action>
      <NSpace
        justify="center"
        style="padding-bottom: 20px"
      >
        <NButton @click="routeReplace">取消</NButton>
        <NButton
          @click="submit"
          :disabled="loading"
          :loading="loading"
        >
          确定
        </NButton>
      </NSpace>
    </template>
  </ModalContent>
</template>
